package org.maxgroundstation.groundstation.view.map;

/**
 * A utility class for the map display.
 * @author Scott Davis
 * 
 * Copyright (C) 2010  Scott Davis
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
public final class MapUtil {

    // The approximate length of a degree latitude (km).
    private static final double LATITUDE_DEGREE_SIZE = 111D;
    
    // The approximate length of a degree longitude at the equator (km).
    private static final double LONGITUDE_EQUATOR_DEGREE_SIZE = 111D;
    
    /**
     * Private constructor for static utility class.
     */
    private MapUtil() {}
    
    /**
     * Gets the position difference along the X axis for two locations.
     * @param loc1 the first location.
     * @param loc2 the second location.
     * @return X axis difference (meters).
     */
    public static double getXDiff(GpsLocation loc1, GpsLocation loc2) {
        double latitude1Rad = Math.abs(loc1.getLatitude()) * Math.PI / 180D;
        double longitudeLength = Math.cos(latitude1Rad) * LONGITUDE_EQUATOR_DEGREE_SIZE;
        
        return (loc2.getLongitude() - loc1.getLongitude()) * (longitudeLength * 1000D);
    }
    
    /**
     * Gets the position difference along the Y axis for two locations.
     * @param loc1 the first location.
     * @param loc2 the second location.
     * @return Y axis difference (meters).
     */
    public static double getYDiff(GpsLocation loc1, GpsLocation loc2) {
        return (loc2.getLatitude() - loc1.getLatitude()) * (LATITUDE_DEGREE_SIZE * 1000D);
    }
    
    /**
     * Gets the distance between two locations.
     * @param loc1 the first location.
     * @param loc2 the second location.
     * @return distance (meters).
     */
    public static double getDistance(GpsLocation loc1, GpsLocation loc2) {
        
        double xDiff = getXDiff(loc1, loc2);
        double yDiff = getYDiff(loc1, loc2);
        
        return Math.sqrt(Math.pow(xDiff, 2D) + Math.pow(yDiff, 2D));
    }
    
    /**
     * Gets a GPS location given an initial location and a rectangular coordinate offset.
     * @param xDiff the x offset (m).
     * @param yDiff the y offset (m).
     * @param loc the initial GPS location.
     * @return new GPS location.
     */
    public static GpsLocation getNewGpsLocation(double xDiff, double yDiff, GpsLocation loc) {
        double latitudeRad = Math.abs(loc.getLatitude()) * Math.PI / 180D;
        double longitudeLength = Math.cos(latitudeRad) * LONGITUDE_EQUATOR_DEGREE_SIZE * 1000D;
        double latitudeLength = LATITUDE_DEGREE_SIZE * 1000D;
        
        double newLongitude = loc.getLongitude() + (xDiff / longitudeLength);
        double newLatitude = loc.getLatitude() + (yDiff / latitudeLength);
        
        return new GpsLocation(newLatitude, newLongitude);
    }
}